package com.solarStruggle.controls

import java.awt.{Color, Font, Insets}
import javax.swing.{ImageIcon}
import javax.swing.border.{EmptyBorder, LineBorder}
import scala.swing.{Alignment, Button, Component, Dialog, Frame, GridBagPanel, Label, ListView, ScrollPane, TabbedPane, TextField}
import scala.swing.event.{ButtonClicked, ListSelectionChanged, ValueChanged}

import domain.{Chassis, Engine, Material, Pod, Shard, ShardRegistry, Shield, Vehicle, Weapon}
import graphics.Svg
import util.{Misc, ResourceLoader}

/**
 * This class provides a drop-in control for creating a vehicle from a list of available shards
 */
class VehicleCreator
extends Frame {

	var result = Dialog.Result.Cancel
	val vehicle: Vehicle = new Vehicle

	contents = new MigPanel {

	val vehicleInfo = new VehicleInfo {
		data = Some(vehicle)
	}
	val vehicleComponentsInfo = new VehicleComponentsInfo {
		data = Some(vehicle)
	}

	val chassisSelector = new ShardSelector[Chassis](ShardRegistry.chassis, new ChassisInfo) {
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.chassis = shards.map { a => a.asInstanceOf[Chassis] }
				weaponSelector.maxShards = vehicle.maxWeapons
				enginesSelector.maxShards = vehicle.maxEngines
				podSelector.maxShards = vehicle.maxPods
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val materialSelector = new ShardSelector[Material](ShardRegistry.materials, new MaterialInfo) {
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.material = shards.map { a => a.asInstanceOf[Material] }
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val shieldSelector = new ShardSelector[Shield](ShardRegistry.shields, new ShieldInfo) {
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.shield = shards.map { a => a.asInstanceOf[Shield] }
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val enginesSelector = new ShardSelector[Engine](ShardRegistry.engines, new EngineInfo) {
		maxShards = 0
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.engines = shards.map { a => a.asInstanceOf[Engine] }
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val weaponSelector = new ShardSelector[Weapon](ShardRegistry.weapons, new WeaponInfo) {
		maxShards = 0
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.weapons = shards.map { a => a.asInstanceOf[Weapon] }
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val podSelector = new ShardSelector[Pod](ShardRegistry.pods, new PodInfo) {
		maxShards = 0
		reactions += {
			case SelectedShardChanged(_, shards) => 
				vehicle.pods = shards.map { a => a.asInstanceOf[Pod] }
				vehicleInfo.refresh()
				vehicleComponentsInfo.refresh()
		}
	}

	val nameInput: TextField = new TextField {
		reactions += {
			case ValueChanged(_) => 
				vehicle.name = nameInput.text
		}
	}

	val okButton = new Button("Ok") {
		reactions += {
			case ButtonClicked(_) =>
				result = Dialog.Result.Ok
				VehicleCreator.this.visible = false
		}
	}

	val cancelButton = new Button("Cancel") {
		reactions += {
			case ButtonClicked(_) =>
				result = Dialog.Result.Cancel
				VehicleCreator.this.visible = false
		}
	}

	add(new Label("Name"), "growx 0, shrink")
	add(nameInput, "growx, wrap")
	add(new TabbedPane {
		pages += new TabbedPane.Page("Frame", chassisSelector)
		pages += new TabbedPane.Page("Material", materialSelector)
		pages += new TabbedPane.Page("Shield", shieldSelector)
		pages += new TabbedPane.Page("Engines", enginesSelector)
		pages += new TabbedPane.Page("Weapons", weaponSelector)
		pages += new TabbedPane.Page("Pods", podSelector)
	}, "growx, growy, spanx 2, wrap")

	add(vehicleComponentsInfo, "width 300, growx")
	add(vehicleInfo, "width 300, growx, wrap")
	add(okButton, "spanx 2, align r, tag ok, split")
	add(cancelButton, "align r, tag cancel")
}
}

/**
 * Base class for info displays on the vehicle creator.  Sets the common 
 * font/style
 */
class VehicleCreatorInfo[A]
extends InfoDisplay[A] {
}

/**
 * Base class for showing info on subclasses of Shard
 */
class ShardInfo[A <: Shard]
extends VehicleCreatorInfo[A] {

	fields.add("Name", { a => a.name })
	fields.add("Cost", { a => a.cost.toString })
	fields.add("Research Cost", { a => a.researchCost.toString })
	fields.add("Mass", { a => a.mass.toString })
	fields.add("Energy", { a => a.energy.toString})
}

/**
 * Info display for chassis
 */
class ChassisInfo 
extends ShardInfo[Chassis] {
	fields.add("Maximum # Engines", { a => a.maxEngines.toString })
	fields.add("Maximum # Weapons", { a => a.maxWeapons.toString })
	fields.add("Maximum # Pods", { a => a.maxPods.toString })
}

/**
 * Info display for materials
 */
class MaterialInfo 
extends ShardInfo[Material] {
	fields.add("Defense", { a => a.defense.toString })
}

/**
 * Info display for shields
 */
class ShieldInfo
extends ShardInfo[Shield] {
	fields.add("Physical Defense", { a => a.physicalDef.toString })
	fields.add("Energy Defense", { a => a.energyDef.toString })
}

class EngineInfo
extends ShardInfo[Engine] {
	fields.add("Force", { a => a.force.toString })
}

/**
 * Info display for weapons
 */
class WeaponInfo
extends ShardInfo[Weapon] {
	fields.add("Inside Radius", { a => a.insideRadius.toString })
	fields.add("Outside Radius", { a => a.outsideRadius.toString })
	fields.add("Physical Damage", { a => a.physicalDamage.toString })
	fields.add("Energy Damage", { a => a.energyDamage.toString })
	fields.add("Blast Radius", { a => a.blastRadius.toString })
}

class PodInfo
extends ShardInfo[Pod] {
}

/**
 * Info display for vehicle
 */
class VehicleInfo
extends VehicleCreatorInfo[Vehicle] {
	fields.add("Name", { a => a.name })
	fields.add("Total Cost", { a => a.totalCost.toString })
	fields.add("Total Research Cost", { a => a.totalResearchCost.toString })
	fields.add("Total Mass", { a => a.totalMass.toString })
	fields.add("Available Energy", { a => (-a.totalEnergy).toString })
	fields.add("Available Engine Slots", { a => a.availableEngines.toString })
	fields.add("Available Weapon Slots", { a => a.availableWeapons.toString })
	fields.add("Available Pod Slots", { a => a.availablePods.toString })
}

class VehicleComponentsInfo
extends VehicleCreatorInfo[Vehicle] {
	fields.add("Frame", { a => Misc.listToString(a.chassis, "", ", ", "", 10) })
	fields.add("Material", { a => Misc.listToString(a.material, "", ", ", "", 10) })
	fields.add("Shields", { a => Misc.listToString(a.shield, "", ", ", "", 10) })
	fields.add("Weapons", { a => Misc.listToString(a.weapons, "", ", ", "", 10) })
	fields.add("Engines", { a => Misc.listToString(a.engines, "", ", ", "", 10) })
	fields.add("Pods", { a => Misc.listToString(a.pods, "", ", ", "", 10) })
}
